//////////////////////////////////////////////////////////////////////////
//
// GAM203
// Mesh Basic
// MeshBasic.cpp
// 
// Grant Johnson
// Qantm College
// 27/10/2010
//
//////////////////////////////////////////////////////////////////////////

#include "MeshBasic.h"
#include "Shader.h"
#include "ShaderMgr.h"
#include "RenderParams.h"
#include <d3dx9.h>
#include "Renderer.h"

MeshBasic::MeshBasic()
: m_pMesh(NULL)
, m_angle(0)
{
}

MeshBasic::~MeshBasic()
{
	if (m_pMesh)
	{
		m_pMesh->Release();
		m_pMesh = NULL;
	}
}
bool MeshBasic::CreateObject(IDirect3DDevice9* a_pDevice, char* a_pTexFileName)
{
	if (!a_pDevice)
	{
		return false;
	}

	// Create a shape in our mesh helper
	HRESULT result = D3DERR_INVALIDCALL;

	result = D3DXCreateTorus(a_pDevice, 0.5f, 2.0f, 100, 100, &m_pMesh, NULL);
	if (result != D3D_OK)
	{
		return false;
	}

	DWORD* pVertices = NULL;
	m_pMesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&pVertices);

	//Calculate the bounding box
	D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, m_pMesh->GetNumVertices(), D3DXGetFVFVertexSize(m_pMesh->GetFVF()), &m_aabb.GetMin(), &m_aabb.GetMax());

	m_pMesh->UnlockVertexBuffer();

	// Set up our material
	ZeroMemory(&m_mtl, sizeof(m_mtl));  // Zero out the material (ie. all colours black, power set to zero)
	//m_mtl.Ambient = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	m_mtl.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);

	D3DXMatrixTranslation(&m_worldMatrix, 10, 10, 10);

	return true;
}

void MeshBasic::Render(float a_dt, IDirect3DDevice9* a_pDevice, const RenderParams& a_renderParams)
{
	if (a_pDevice && m_pMesh)
	{
		// Set up our world transform
		a_pDevice->SetTransform(D3DTS_WORLD, &m_worldMatrix);

		const char* SHADER_NAME = "AdvancedShader";
		Shader* pShader = ShaderMgr::GetInstance().Find(SHADER_NAME);
		if(pShader)
		{
			ID3DXEffect* pEffect = pShader->GetEffect();
			if(pEffect)
			{

				pEffect->SetTechnique("AdvRenderDiff0Spec0Dir1Omni1Col");

				//Set material global variables
				pEffect->SetValue("g_materialAmbientColor", &D3DXCOLOR(m_mtl.Ambient), sizeof(D3DXCOLOR));
				pEffect->SetValue("g_materialDiffuseColor", &D3DXCOLOR(m_mtl.Diffuse), sizeof(D3DXCOLOR));
				pEffect->SetValue("g_materialSpecularColor", &D3DXCOLOR(m_mtl.Specular), sizeof(D3DXCOLOR));
				pEffect->SetValue("g_materialEmissiveColor", &D3DXCOLOR(m_mtl.Emissive), sizeof(D3DXCOLOR));
				pEffect->SetFloat("g_materialSpecularPower", m_mtl.Power);

				pEffect->SetValue("g_fogColor", &D3DXCOLOR(0.3f, 0.35f, 0.4f, 1.0f), sizeof(D3DXCOLOR));

				pEffect->SetFloat("g_fogDistStart", 10);
				pEffect->SetFloat("g_fogDistEnd", 200);
				pEffect->SetValue("g_cameraPos", Renderer::GetInstance().GetActiveCamera()->GetEyePos(), sizeof(D3DXVECTOR3));

				//Set up lighting global variables
				for(int lightId = 0; lightId < a_renderParams.GetLightCount(); ++lightId)
				{
					if(a_renderParams.GetLight(lightId)->Type == D3DLIGHT_DIRECTIONAL)
					{
						//Set lighting parameters
						//Note: Light direction is negated to optimise the dot product in 
						//shader calculations
						pEffect->SetValue("g_directionalDir", &(D3DXVECTOR3(a_renderParams.GetLight(lightId)->Direction) * -1.0f), sizeof(D3DXVECTOR3));
						pEffect->SetValue("g_directionalDiffuse", &D3DXCOLOR(a_renderParams.GetLight(lightId)->Diffuse), sizeof(D3DXCOLOR));
						pEffect->SetValue("g_directionalSpecular", &D3DXCOLOR(a_renderParams.GetLight(lightId)->Specular), sizeof(D3DXCOLOR));
					}
					else if(a_renderParams.GetLight(lightId)->Type == D3DLIGHT_POINT)
					{
						pEffect->SetValue("g_omniPos", &D3DXVECTOR3(a_renderParams.GetLight(lightId)->Position), sizeof(D3DXVECTOR3));
						pEffect->SetFloat("g_omniRange", a_renderParams.GetLight(lightId)->Range);
						pEffect->SetValue("g_omniDiffuse", &D3DXCOLOR(a_renderParams.GetLight(lightId)->Diffuse), sizeof(D3DXCOLOR));
						pEffect->SetValue("g_omniSpecular", &D3DXCOLOR(a_renderParams.GetLight(lightId)->Specular), sizeof(D3DXCOLOR));
					}
				}
				pEffect->SetValue("g_totalAmbient", &D3DXCOLOR(a_renderParams.GetGlobalAmbient()), sizeof(D3DXCOLOR));
				
				//Set matrix global variables
				//Calculate a combined world*view*proj matrix for the vertex shader
				D3DXMATRIX worldViewProj = m_worldMatrix*a_renderParams.GetViewMatrix()*a_renderParams.GetProjMatrix();
				pEffect->SetMatrix("g_worldViewProj", &worldViewProj);
				pEffect->SetMatrix("g_worldMat", &m_worldMatrix);

				//Render with shader
				UINT passCount = 0;
				if(pEffect->Begin(&passCount, 0) == D3D_OK)
				{
					for(UINT passIndex = 0; passIndex < passCount; ++passIndex)
					{		
						if(pEffect->BeginPass(passIndex) == D3D_OK)
						{
							// Draw the mesh segment
							HRESULT result = m_pMesh->DrawSubset(0);
							if(result != D3D_OK)
							{
								return;
							}
							pEffect->EndPass();
						}
					}
					pEffect->End();
				}
			}
		}
	}
}



